package UserProfile;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;

import com.hp.hpl.jena.ontology.OntModel;

import IMDBQuery.IMDBReader;
import IMDBQuery.MovieIMDB;
import IMDBQuery.*;
import Recomendadores.RecomendadorPorContenido;
import Recomendadores.Semantico.RecomendadorSemantico;
import java.util.logging.Level;
import java.util.logging.Logger;

public class UserProfile {

    /**
     * Metodo encargado de crear los perfiles de usuario a partir de las bases
     * MovieLens
     */
    public static void cargarPerfilesUsuario(int numCalf) {
        //obtengo las configuraciones del sistema
        Configuration conf = Configuration.getInstance();

        //obtengo la lista de peliculas definidas en DBMOVIES (base de peliculas)
        ArrayList<String> movies = UserDataFileReader.readLines(conf.getDBMOVIES());

        //obtengo las calificaciones agrupadas por usuario de la DBRATINGS (base de ratings)
        ArrayList<ArrayList<Calificacion>> agrupados = UserDataFileReader.RatingsReadLines(conf.getDBRATINGS());
        Iterator<ArrayList<Calificacion>> ite = agrupados.iterator();
        //recorro los grupos, osea recorro los usuarios
        while (ite.hasNext()) {
            try {
                ArrayList<Calificacion> grupo = ite.next();
                /*ArrayList<Calificacion> grupo = new ArrayList<Calificacion>();
                 if (numCalf == 0) {
                 numCalf = grupo1.size();
                 }
                 for (int i = 0; i < numCalf; i++) {
                 if (grupo1.size() >= numCalf) {
                 grupo.add(grupo1.get(i));
                 }
                 }*/
                if (!grupo.isEmpty()) {
                    System.out.println("");
                    System.out.println("user " + grupo.get(0).getIdUser());

                    //obtengo el perfil-ontologia de usuario, si no existe se crea
                    OntModel user = UserOntologyManager.getUserModel(grupo.get(0).getIdUser(), conf);
                    int cont = 0;
                    Iterator<Calificacion> ite2 = grupo.iterator();
                    //recorro las calificaciones del usuario
                    while (ite2.hasNext()) {
                        cont++;
                        Calificacion cal = ite2.next();

                        System.out.print("|");

                        //compruebo que la pelicula sea de train o de test
                        boolean isTest = isTestMovie(cal, conf);
                        //boolean isTest = false;
//                        if (isTest || cont <= numCalf) {
                            //encuentro la pelicula en la lista
                            String movieLine = findMovieLine(cal.getIdMovie(), movies);

                            //cargo la MovieIMDB
                            MovieIMDB movieIMDb = IMDBReader.getMovieIMDB(movieLine, conf);

                            //cargo la pelicula en el modelo
                            if (movieIMDb != null) {
                                user = UserOntologyManager.fillOntology(user, movieIMDb, cal, conf, isTest);
                            }
//                        }
                    }

                    //propago los DOI en las caracteristicas semanticas de los contenidos formalizados en la ontologia
                    user = UserOntologyManager.doiPropagation(user, grupo.get(0).getIdUser(), conf, true);

                    //guardo el perfil-ontolog�a
                    try {
                        String path = conf.getONTOLOGYUSER() + grupo.get(0).getIdUser() + ".owl";
                        FileWriter f1 = new FileWriter(path);
                        BufferedWriter b1 = new BufferedWriter(f1);
                        user.write(b1, "RDF/XML");
                        b1.close();
                        user.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        System.out.println(e.getMessage());

                    }
                }
            } catch (NoExisteLaOntologiaException e) {
                // TODO Auto-generated catch block
                System.out.println("UserProfile.cargarPerfilesUsuario() Error: " + e.getMessage());
            } catch (NoSePudoPersistirElModeloException e) {
                // TODO Auto-generated catch block
                System.out.println("UserProfile.cargarPerfilesUsuario() Error: " + e.getMessage());
            }
        }
    }

    /**
     * Metodo encargado de crear las ontologias de peliculas de las bases
     * MovieLens
     */
    public static void cargarPelicula() {
        try {
            //obtengo las configuraciones del sistema
            Configuration conf = Configuration.getInstance();

            //obtengo la lista de peliculas definidas en DBMOVIES (base de peliculas)
            ArrayList<String> movies = UserDataFileReader.readLines(conf.getDBMOVIES());

            //obtengo el perfil-ontologia de pelicula, si no existe se crea
            OntModel movie = UserOntologyManager.getMovieModel(conf);
            int count = 0;
            while (movies.size() >= count) {
                count++;
                //encuentro la pelicula en la lista
                String movieLine = findMovieLine(count, movies);
                //cargo la MovieIMDB
                MovieIMDB movieIMDb = IMDBReader.getMovieIMDB(movieLine, conf);
                System.out.println("|" + count + "sss" + movieIMDb);

                //cargo la pelicula en el modelo
                if (movieIMDb != null) {
                    movie = UserOntologyManager.fillOntology(movie, movieIMDb, conf);
                }
                //guardo el perfil-ontolog�a
                String path = conf.getMOVIESIMDB();
                System.err.println(path);
                FileWriter f1;
                try {
                    f1 = new FileWriter(path);
                    BufferedWriter b1 = new BufferedWriter(f1);
                    movie.write(b1, "RDF/XML");
                    b1.close();

                } catch (IOException ex) {
                    Logger.getLogger(UserProfile.class.getName()).log(Level.SEVERE, null, ex);
                }

            }
            movie.close(); //cerramos la ontologia
        } catch (NoSePudoPersistirElModeloException ex) {
            Logger.getLogger(UserProfile.class.getName()).log(Level.SEVERE, null, ex);
        } catch (NoExisteLaOntologiaException ex) {
            Logger.getLogger(UserProfile.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    /**
     * Retorna true en caso de que la pelicula calificada sea de test
     *
     * @param calification es la calificacion que un usuario da a una pelicula
     * @param conf es la configuracion del sistema
     * @return true si la pelicula es de test, false en caso contrario
     */
    private static boolean isTestMovie(Calificacion calificacion, Configuration conf) {

        //obtengo las peliculas test agrupadas por usuario de DBTEST (base de peliculas para test)
        ArrayList<ArrayList<Calificacion>> agrupados = UserDataFileReader.RatingsReadLines(conf.getDBTEST());
        Iterator<ArrayList<Calificacion>> ite = agrupados.iterator();
        //recorro los grupos, osea recorro los usuarios
        while (ite.hasNext()) {
            ArrayList<Calificacion> grupo = ite.next();
            if (!grupo.isEmpty()) {
                //obtengo el id del usuario puntero
                int iduser = grupo.get(0).getIdUser();
                /*si el usuario puntero coinside con el usuario buscado 
                 se comprueba si la pelicula calificada es de test*/
                if (iduser == calificacion.getIdUser()) {
                    Iterator<Calificacion> ite2 = grupo.iterator();
                    //recorro las calificaciones del usuario puntero
                    while (ite2.hasNext()) {
                        Calificacion cal = ite2.next();
                        //compruebo que la pelicula buscada este entre las peliculas test del usuario
                        if (cal.getIdMovie() == calificacion.getIdMovie()) {
                            return true;
                        }
                    }
                    //si no esta entre las peliculas test retorno false;
                    return false;
                }
            }
        }
        return false;
    }

    /**
     * Retorna la informacion del contenido identificado con
     * <code>idMovie</code> de la lista de contenidos <code>movies</code>
     *
     * @param idMovie identificador del contenido buscado
     * @param movies lista de los contenidos definidos en la base de datos de
     * MovieLens
     * @return informacion del contenido buscado
     */
    private static String findMovieLine(int idMovie, ArrayList<String> movies) {
        Iterator<String> iterator = movies.iterator();
        while (iterator.hasNext()) {
            String pivot = iterator.next();
            String campos[] = pivot.split("::");
            int idMoviePivot = Integer.parseInt(campos[0]);

            if (idMovie == idMoviePivot) {
                return pivot;
            }
        }
        return null;
    }

    public static void main(String[] args) {
   // ClasificacionTranningTest.ClasificarTranningTest();
//   cargarPerfilesUsuario(0); 
          String par="";
          for(int i=2;i<54;i=i+2){
        NearestNeighbors.allNeightbors(1000,5,(0.086666666f*i));
//          cargarPelicula();
   //     RecomendadorPorContenido.recomendadorPorContenido();
//		RecomendadorSemantico.recomendar();
//		RecomendadorSemantico.recomendarPorDispersion();
            par="cambio distancia:"+(0.086666666f*i);
            RecomendadorSemantico.recomedarPorNN(par);
            }
            
            
//                RecomendadorSemantico.recomendarConSecuencia();
//                RecomendadorSemantico.recomendarPor("Genre,Actor,Director,Writer,Imdb");// puede ser por Genre,Actor,Director,Writer,Imdb y cualquiera de sus combinaciones
           //   RecomendadorSemantico.recomedarPorEstereotipos("Genre");
     /*   try {
            String propiedades = "Genre,Actor,Writer,Director";
            Configuration conf = Configuration.getInstance();
            FileWriter f1;
            f1 = new FileWriter(Configuration.getInstance().getOUTRECOMMENDATION() + "RECNUMUSSERS.dat");
            BufferedWriter b1 = new BufferedWriter(f1);
            double error;
            for (int i = 1; i < 825; i++) {
                cargarPerfilesUsuario(i);
                error = RecomendadorSemantico.recomendarConSecuencia();
                String linea = i + "::" + error;
                b1.write(linea);
                b1.newLine();
                b1.flush();
                System.err.println("------------- Se guarda con : " + i + " Usuarios");
            }
            f1.close();*/
            //          cargarPelicula();

//		RecomendadorSemantico.recomendar();
//		RecomendadorSemantico.recomendarPorDispersion();
            //       RecomendadorSemantico.recomendarPor("Genre");// puede ser por Genre,Actor,Director,Writer,Imdb y cualquiera de sus combinaciones
            //   RecomendadorSemantico.recomedarPorEstereotipos("Genre");
            /*   try {
             String propiedades = "Genre,Actor,Writer,Director";
             Configuration conf = Configuration.getInstance();
            
            
             double wGenres;
             double wActors, wDirectors, wWtriters;
             wActors = wDirectors = wWtriters = wGenres = 0.25d;
            
             for (wWtriters=0.1;wWtriters<0.94;wWtriters+=0.03) {
             //cargarPerfilesUsuario(i);
             wGenres=wActors=wDirectors=((1d-wWtriters)/3d);
             double error = RecomendadorSemantico.recomendarPonderadaPor(propiedades, wGenres, wActors, wDirectors, wWtriters, 1);
             String linea = wWtriters + "::" + error;
             b1.write(linea);
             b1.newLine();
             b1.flush();
             System.err.println("------------- Se guarda con : " + wWtriters + "");
             }
             f1.close();
            
             } catch (IOException ex) {
             Logger.getLogger(UserProfile.class.getName()).log(Level.SEVERE, null, ex);
             }
            
             //RecomendadorSemantico.recomendarUser(1);
        } catch (Exception ex) {
            Logger.getLogger(UserProfile.class.getName()).log(Level.SEVERE, null, ex);
        }*/
    }

}
